import React,{useState,useEffect,useRef} from 'react'
//useRef
// 概念解释：钩住某些组件挂载完成或重新渲染完成后才拥有的某些对象，并返回该对象的引用
// 该引用在组件整个生命周期内都固定不变，该引用并不会随着组件重新渲染而失效
// 某些对象：JSX组件转换后对应的真实DOM对象，在useEffect中创建的变量，子组件内自定义的函数方法
// 1 例如访问<inpiut />
// 2 useEffect中创建的变量

// 基本用法
//useRef(initialVal)函数只有1个可选参数，该参数为默认钩住的对象
// 绝大多数情况默认钩住的对象在jsx未编译前根本不存在，更多时候传一个null为默认值，不传则为undefined

// useRef(null)和useRef() 在ts中是有差别的
// 例如
// const canvasRef1 = useRef<HTMLCanvasElement>(null) 类型为 HTMLCavasElement | null
// const canvasRef2 = useRef(HTMLCanvasElement) 类型为HTMLCanvasElement | null | undefined

//用法
// 1 针对JSX组件，通过ref = {xxxRef}进行关联
// 2 针对useEffect中的变量，通过xxxRef.current进行关联

// 代码形式
// 先定义一个xxxRef引用变量，用于钩住某些组件挂载完成或重新渲染完成后才拥有的某些对象
// const xxRef = useRef(null)
// 针对JSX组件，通过属性ref = {xxxRef} 进行关联
// <xxx ref={xxRef}>
// 针对useEffect中的变量，通过xxxRef.current关联
// useEffect(() => {
//     xxRef.current = xxx
// },[])


// 示例1
// r若我们有一个组件，该组件只有一个输入框，希望在组件挂载到网页后，自动获得输入焦点
// function App () {
//     const inputRef = useRef(null) //先定义一个inputRef引用变量，用于钩住挂载网页后的输入框
//     useEffect(() => {
//         inputRef.current.focus()
//     },[])
//     return (
//         <div>
//             {/*通过ref属性将inputRef与该输入框进行挂钩*/}
//             <input type="text" ref={inputRef}/>
//         </div>
//     )
// }

// 示例2
// 需求：组件中有一个变量count,当该组件挂载到网页后，count每秒+1;组件有一个按钮，点击按钮停止count自动+1
// function App () {
//     const [count,setCount] = useState(0)
//     const timerRef = useRef(null)
//     useEffect(() => {
//         //需要用setTimer()包裹住 setInterval()
//         // ts 语法下setinteval会报错，不能将类型timeout分配类型number
//         // 原因: ts实在node环境下,编译后是在window，各自有各自的定时器
//         timerRef.current = setInterval(() => {
//             setCount((pre) => {return pre + 1})
//         },1000)
//         return () => {
//             clearInterval(timerRef.current)
//         }
//     },[])
//     const clickHandler = () => {
//         clearInterval(timerRef.current)
//     }
//     return (
//         <div>
//             {count}
//             <button onClick={clickHandler}>stop</button>
//         </div>
//     )
// }

// ts版本
// const MyTemp = () => {
//     const timer = useRef<number | undefined>() // const myRef = useRef<Xxx | null>(null)
//     useEffect(() => {
//         timer.current = window.setInterval(() => {
//             console.log('...')
//         },1000)
//     },[])
//     return () => {
//         clearInterval(timer.current)
//     }
//     return (
//         <div></div>
//     )
// }

//钩住自定义组件中的“小写开头的类似原生标签的组件”
function UseRef () {
    const ref = useRef() // 父组件定义一个ref
    const clickHandler = () => {
        console.log(ref.current)
    }
    return (
        <div>
            {/* 父组件通过给子组件添加属性 ref={ref} 将ref作为参数传递给子组件 */}
            <ChildComponent label={'child'} ref={ref}></ChildComponent>
            <button onClick={clickHandler}>get child</button>
        </div>
    )
}

const ChildComponent = React.forwardRef((props,ref) => {
    const clickHandler = () => {
        console.log('获取到了')
    }
    //子组件通过将第2个参数ref 添加到内部真正的“小写开头的类似原生标签的组件”中
    return <button onClick={clickHandler} ref={ref}>{props.label}</button>
})
export default UseRef;
